package com.example.netcomponent.net;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.TextUtils;

import com.example.netcomponent.net.download.DownloadProgressListener;
import com.example.netcomponent.net.utils.LogUtils;
import com.example.netcomponent.net.utils.ToastUtils;
import com.trello.rxlifecycle.components.support.RxAppCompatActivity;

import java.lang.ref.SoftReference;
import java.net.ConnectException;
import java.net.SocketTimeoutException;

import retrofit2.HttpException;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;

/**
 * Created by zengxianghui900 on 17/10/4.
 * 自定义带加载框的subscriber,请求开始展示
 * 完成则结束，加载框内容可自定义
 */

public class ProgressSubscriber<T> extends Subscriber<T> implements DownloadProgressListener {
    /**请求数据*/
    private BaseApi mBaseApi;
    /**接口*/
    private HttpOnNextListener mHttpOnNextListener;

    /**软引用上下文，防止内存泄漏*/
    private SoftReference<RxAppCompatActivity> mActivity;
    /**加载进度框 */
    private ProgressDialog mDialog;


    public ProgressSubscriber(BaseApi<T> baseApi) {
        this.mBaseApi = baseApi;
        this.mHttpOnNextListener = baseApi.getListener();
        this.mActivity = new SoftReference<RxAppCompatActivity>(baseApi.getRxAppCompatActivity());

        String showProgress = baseApi.getProgressMsg();
        //加载框内容不为空，则表示要显示加载进度框
        if (!TextUtils.isEmpty(showProgress)){
            initProgressDialog(baseApi.isCancel(),showProgress);
        }
    }

    /**
     * 初始化加载弹窗
     * @param cancel  是否可取消加载框
     * @param showProgress 加载框显示的内容
     */
    private void initProgressDialog(boolean cancel, String showProgress) {

        RxAppCompatActivity context = mActivity.get();
        if (mDialog == null && context != null){
            mDialog = new ProgressDialog(context);
            mDialog.setMessage(showProgress);
            mDialog.setCancelable(cancel);
            if (cancel) {
                mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        //判断一下是否为空
                        HttpOnNextListener listener = mHttpOnNextListener;
                        if (listener != null) {
                            //回调
                            listener.onCancel();
                        }
                        //取消的同时，取消订阅
                        onCancelSubscriber();
                    }
                });
            }


        }



    }

    /**
     * 点击外部取消弹窗时，也取消订阅，同时取消网络请求
     */
    private void onCancelSubscriber() {
        if (this.isUnsubscribed()){
            this.unsubscribe();
        }

    }


    @Override
    public void onStart() {
        //弹出加载进度框
        showProgressDialog();
    }



    @Override
    public void onCompleted() {
        dismissDialog();
    }



    @Override
    public void onError(Throwable e) {
        dismissDialog();
        //对错误进行处理
        doError(e);
    }



    @Override
    public void onNext(T t) {
        HttpOnNextListener listener = mHttpOnNextListener;
        if (t != null && listener != null) {
            listener.onNext(t);
        }
    }

    /**
     * 显示进度框
     */
    private void showProgressDialog() {
        if (TextUtils.isEmpty(mBaseApi.getProgressMsg()) || mDialog == null || mActivity.get() == null){
            return;
        }

        if (!mDialog.isShowing()){
            mDialog.show();
        }

    }

    /**
     * 取消进度框
     */
    private void dismissDialog() {
        if(mDialog != null && mDialog.isShowing()){
            mDialog.dismiss();
        }
    }

    /**
     * 统一处理错误信息
     * @param e
     */
    private void doError(Throwable e) {

        Context context = mActivity.get();
        if (context == null) return;
        if (e instanceof SocketTimeoutException) {
            ToastUtils.showShortToast(context, AppConstant.Net.SOCKET_TIMEOUT_FAIL);
        } else if (e instanceof ConnectException) {
            ToastUtils.showShortToast(context, AppConstant.Net.CONNECT_FAIL);
        }else if (e instanceof java.net.UnknownHostException) {     //无法解决地址名
            ToastUtils.showShortToast(context, AppConstant.Net.OTHER_CONNECT_FAIL);
        } else if (e instanceof HttpException){
            ToastUtils.showShortToast(context, AppConstant.Net.BUSY_NET_FAIL);
        }else{
            ToastUtils.showShortToast(context, e.getMessage());
            String error=e.getMessage();
            StackTraceElement[] stackTrace = e.getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                error += stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() +"(" + stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber()+") \n";
            }
            LogUtils.e("zxh","doError==" + error);
            //存储一下错误日志
            LogUtils.saveLogToSD(LogUtils.INTERFACE_MODULE,error);
        }

        if (mHttpOnNextListener != null) {
            mHttpOnNextListener.onError(e);
        }
    }

    @Override
    public void update(long read, final long count, boolean done) {
        //如果要回调就设置showProgress为true
        if (mHttpOnNextListener != null && mBaseApi.isShowProgress()) {
            /*接受进度消息，造成UI阻塞，如果不需要显示进度可去掉实现逻辑，减少压力*/
            rx.Observable.just(read).observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<Long>() {
                        @Override
                        public void call(Long aLong) {
                            mHttpOnNextListener.updateProgress(aLong,count);
                        }
                    });
        }
    }
}
